import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

public class Test {

        // 虚拟线程（Virtual Thread）是Java 19引入的一种轻量级线程，它在很多其他语言中被称为协程、纤程、绿色线程、用户态线程等。
        // 在理解虚拟线程前，我们先回顾一下线程的特点：
        // 线程是由操作系统创建并调度的资源；
        // 线程切换会耗费大量CPU时间；
        // 一个系统能同时调度的线程数量是有限的，通常在几百至几千级别。
        // 因此，我们说线程是一种重量级资源。在服务器端，对用户请求，通常都实现为一个线程处理一个请求。由于用户的请求数往往远超操作系统能同时调度的线程数量，所以通常使用线程池来尽量减少频繁创建和销毁线程的成本。
        public static void main(String[] args) throws Exception {
                // 方法一：传入Runnable实例并立刻运行:
                Thread vt = Thread.startVirtualThread(() -> {
                        System.out.println("Start virtual thread...");
                        try {
                                Thread.sleep(10);
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                        System.out.println("End virtual thread.");
                });
                // 方法二：创建VirtualThread:
                Thread vt1 = Thread.ofVirtual().unstarted(() -> {
                        System.out.println("Start virtual thread...");
                        try {
                                Thread.sleep(10);
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                        System.out.println("End virtual thread.");
                });
                // 运行:
                vt1.start();

                // 方法三：通过虚拟线程的ThreadFactory创建虚拟线程，然后手动调用start()开始运行：

                // 创建ThreadFactory:
                ThreadFactory tf = Thread.ofVirtual().factory();
                // 创建VirtualThread:
                Thread vt3 = tf.newThread(() -> {
                        System.out.println("Start virtual thread...");
                        try {
                                Thread.sleep(10);
                        } catch (Exception e) {
                                e.printStackTrace();
                        }
                        System.out.println("End virtual thread.");
                });
                // 运行:
                vt3.start();

                // 直接调用start()实际上是由ForkJoinPool的线程来调度的。我们也可以自己创建调度线程，然后运行虚拟线程：
                // // 创建调度器:
                // ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
                // // 创建大量虚拟线程并调度:
                // ThreadFactory tf = Thread.ofVirtual().factory();
                // for (int i=0; i<100000; i++) {
                // Thread vt = tf.newThread(() -> { ... });
                // executor.submit(vt);
                // // 也可以直接传入Runnable或Callable:
                // executor.submit(() -> {
                // System.out.println("Start virtual thread...");
                // Thread.sleep(1000);
                // System.out.println("End virtual thread.");
                // return true;
                // });
                // }
                Thread.sleep(2000);
        }
}

// 使用限制
// 注意到只有以虚拟线程方式运行的代码，才会在执行IO操作时自动被挂起并切换到其他虚拟线程。普通线程的IO操作仍然会等待，例如，我们在main()方法中读写文件，是不会有调度和自动挂起的。

// 可以自动引发调度切换的操作包括：

// 文件IO；
// 网络IO；
// 使用Concurrent库引发等待；
// Thread.sleep()操作。
// 这是因为JDK为了实现虚拟线程，已经对底层相关操作进行了修改，这样应用层的Java代码无需修改即可使用虚拟线程。无法自动切换的语言需要用户手动调用await来实现异步操作：

// async function doWork() {
// await readFile();
// await sendNetworkData();
// }
// 在虚拟线程中，如果绕过JDK的IO接口，直接通过JNI读写文件或网络是无法实现调度的。此外，在synchronized块内部也无法调度